import java.util.PriorityQueue;

public class MyTimer {
    private PriorityQueue<Elem> tasks = new PriorityQueue<>();

    public MyTimer() {
        Thread t = new Thread(() -> {
            while(true) {
                synchronized (this) {
                    while(tasks.isEmpty()) {
                        try {
                            wait();
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    }
                    while(tasks.peek().time > System.currentTimeMillis()) {
                        try {
                            wait(tasks.peek().time - System.currentTimeMillis());
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    }
                    tasks.poll().task.run();
                }
            }
        });

        t.start();
    }

    public void schedule(Runnable task, long delay) {
        long curTime = System.currentTimeMillis();
        synchronized (this) {
            tasks.offer(new Elem(task, curTime + delay));
            notify();
        }
    }
    private static class Elem implements Comparable{
        Runnable task;
        long time;
        public Elem(Runnable task, long time) {
            this.task = task;
            this.time = time;
        }

        @Override
        public int compareTo(Object o) {
            return (int)(this.time - ((Elem)o).time);
        }
    }
}
